using System;
using System.Data;
using System.Data.SqlClient;
using System.Web.Security;
using System.Configuration;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.Administration;
using System.Web.UI.WebControls;
using System.Reflection;

namespace CKS.FormsBasedAuthentication
{
    public class EditMembershipProviders : LayoutsPageBase
    {
        protected InputFormTextBox txtProvidername;
        protected InputFormCheckBox cbDefaultProvider;
        protected InputFormCheckBox cbSQLProvider;
        protected InputFormSection ifsSQLProvider;
        protected InputFormTextBox txtProviderType;
        protected DropDownList ddlConnectionNames;
        protected InputFormCheckBox cbEnablePasswordRetrieval;
        protected InputFormCheckBox cbEnablePasswordReset;
        protected InputFormCheckBox cbRequireQuestionAnswer;
        protected InputFormTextBox txtApplicationName;
        protected InputFormCheckBox cbRequireUniqueEmail;
        protected InputFormRadioButton rbClear;
        protected InputFormRadioButton rbEncrypted;
        protected InputFormRadioButton rbHashed;
        protected InputFormTextBox txtMaxInvalidAttempts;
        protected InputFormTextBox txtMinRequiredPasswordLength;
        protected InputFormTextBox txtMinRequiredNonAlphaChars;
        protected InputFormTextBox txtPasswordAttemptsWindow;
        protected InputFormTextBox txtPasswordStrengthRegEx;
        protected DropDownList ddlProviders;
        protected Button btnDelete;

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                if (Request.Params["Status"] != string.Empty && Request.Params["Status"] == "Success")
                {
                    RegisterClientScriptBlock("Confirmation", "<script>alert('Your Changes Were Made Successfully');</script>");
                }
                FillProviderList();
                FillConnectionNames();
                if (Membership.Provider != null)
                {
                    ddlProviders.SelectedValue = Membership.Provider.Name;
                    LoadProviderData(Membership.Provider.Name);
                }
                //Force the page to setup correctly
                ddlProviders_SelectedIndexChanged(ddlProviders, EventArgs.Empty);

            }
        }

        protected void FillProviderList()
        {
            ddlProviders.Items.Clear();
            ddlProviders.Items.Add(new ListItem("--New--"));
            foreach (MembershipProvider mp in Membership.Providers)
            {
                ddlProviders.Items.Add(mp.Name);
            }
        }

        protected void FillConnectionNames()
        {
            ddlConnectionNames.Items.Clear();
            foreach (System.Configuration.ConnectionStringSettings settings in System.Configuration.ConfigurationManager.ConnectionStrings)
            {
                ddlConnectionNames.Items.Add(new ListItem(settings.Name));
            }
        }

        protected void LoadProviderData(string providerName)
        {
            string connName = string.Empty;
            string connString = string.Empty;
            MembershipProvider provider = null;
            try
            {
                foreach (MembershipProvider mp in Membership.Providers)
                {
                    if (mp.Name == providerName)
                    {
                        provider = mp;
                        break;
                    }
                }
                txtProvidername.Text = provider.Name;
                txtProviderType.Text = provider.GetType().AssemblyQualifiedName;
                if (Membership.Provider.Name == provider.Name)
                {
                    cbDefaultProvider.Checked = true;
                    btnDelete.Enabled = false;            
                }
                else
                {
                    cbDefaultProvider.Checked = false;
                    btnDelete.Enabled = true;
                }
                if (provider is SqlMembershipProvider)
                {
                    ifsSQLProvider.Visible = true;
                    txtProviderType.Enabled = false;
                    //Use Reflection trickery to get connection string
                    FieldInfo connStringFI = provider.GetType().GetField("_sqlConnectionString", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
                    if (connStringFI != null)
                    {
                        connString = (string)connStringFI.GetValue(provider);
                        //Now find the connection string from the config file if it exists
                        foreach (System.Configuration.ConnectionStringSettings settings in System.Configuration.ConfigurationManager.ConnectionStrings)
                        {
                            if (settings.ConnectionString.Equals(connString))   //Found it
                                ddlConnectionNames.SelectedValue = settings.Name;
                        }
                    }
                }
                else
                {
                    txtProviderType.Enabled = true;
                    ifsSQLProvider.Visible = false;
                }
                cbEnablePasswordRetrieval.Checked = provider.EnablePasswordRetrieval;
                cbEnablePasswordReset.Checked = provider.EnablePasswordReset;
                txtApplicationName.Text = provider.ApplicationName;
                cbRequireUniqueEmail.Checked = provider.RequiresUniqueEmail;
                if (provider.PasswordFormat == MembershipPasswordFormat.Clear)
                    rbClear.Checked = true;
                else
                    if (provider.PasswordFormat == MembershipPasswordFormat.Encrypted)
                        rbEncrypted.Checked = true;
                    else
                        rbHashed.Checked = true;
                txtMaxInvalidAttempts.Text = provider.MaxInvalidPasswordAttempts.ToString();
                txtMinRequiredPasswordLength.Text = provider.MinRequiredPasswordLength.ToString();
                txtMinRequiredNonAlphaChars.Text = provider.MinRequiredNonAlphanumericCharacters.ToString();
                txtPasswordAttemptsWindow.Text = provider.PasswordAttemptWindow.ToString();
                txtPasswordStrengthRegEx.Text = provider.PasswordStrengthRegularExpression;
            }
            catch (Exception ex)
            {
                Utils.LogError(ex);
            }
        }

        protected void ddlProviders_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (ddlProviders.SelectedValue == "--New--")
                SetupNewProvider();
            else
                LoadProviderData(ddlProviders.SelectedValue);
        }

        private void SetupNewProvider()
        {
            txtProvidername.Text = "MyMembershipProvider";
            cbDefaultProvider.Checked = false;
            txtProviderType.Text = typeof(SqlMembershipProvider).AssemblyQualifiedName;
            ddlConnectionNames.SelectedIndex = 0;
            cbEnablePasswordRetrieval.Checked = false;
            cbEnablePasswordReset.Checked = true;
            cbRequireQuestionAnswer.Checked = true;
            txtApplicationName.Text = "SharePoint";
            cbRequireUniqueEmail.Checked = true;
            rbHashed.Checked = true;
            txtMaxInvalidAttempts.Text = "5";
            txtMinRequiredPasswordLength.Text = "7";
            txtMinRequiredNonAlphaChars.Text = "1";
            txtPasswordAttemptsWindow.Text = "10";
            txtPasswordStrengthRegEx.Text = string.Empty;
            txtProvidername.Enabled = true;
        }

        protected void OnSubmit(object sender, EventArgs e)
        {
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                System.Configuration.Configuration config = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~");
                System.Web.Configuration.MembershipSection mSection = (System.Web.Configuration.MembershipSection)config.GetSection("system.web/membership");

                if (ddlProviders.SelectedValue == "--New--")
                {
                    //Create the Provider using the settings from the page
                    ProviderSettings pSettings = new System.Configuration.ProviderSettings(txtProvidername.Text, txtProviderType.Text);
                    SetupMembershipProvider(config, ref pSettings);
                    mSection.Providers.Add(pSettings);
                }
                else
                {
                    ProviderSettings pSettings = mSection.Providers[ddlProviders.SelectedValue];
                    SetupMembershipProvider(config, ref pSettings);
                }
                //Save Changes and Reset App
                config.Save(ConfigurationSaveMode.Minimal, false);
                Response.Redirect(Request.Url.ToString() + "?Status=Success");
            });
        }

        protected void cbSQLProvider_CheckChanged(object sender, EventArgs e)
        {
            if (cbSQLProvider.Checked)
            {
                ifsSQLProvider.Visible = true;
                txtProviderType.Enabled = false;
            }
            else
            {
                ifsSQLProvider.Visible = false;
                txtProviderType.Enabled = true;
            }
        }

        private void SetupMembershipProvider(System.Configuration.Configuration config, ref System.Configuration.ProviderSettings pSettings)
        {
            pSettings.Parameters["connectionStringName"] = ddlConnectionNames.SelectedValue;
            pSettings.Parameters["enablePasswordRetrieval"] = cbEnablePasswordRetrieval.Checked.ToString();
            pSettings.Parameters["enablePasswordReset"] = cbEnablePasswordReset.Checked.ToString();
            pSettings.Parameters["requiresQuestionAndAnswer"] = cbRequireQuestionAnswer.Checked.ToString();
            pSettings.Parameters["applicationName"] = txtApplicationName.Text;
            pSettings.Parameters["requiresUniqueEmail"] = cbRequireUniqueEmail.Checked.ToString();
            if (rbClear.Checked)
                pSettings.Parameters["passwordFormat"] = "Clear";
            else
                if (rbEncrypted.Checked)
                    pSettings.Parameters["passwordFormat"] = "Encrypted";
                else
                    pSettings.Parameters["passwordFormat"] = "Hashed";
            pSettings.Parameters["maxInvalidPasswordAttempts"] = txtMaxInvalidAttempts.Text;
            pSettings.Parameters["minRequiredPasswordLength"] = txtMinRequiredPasswordLength.Text;
            pSettings.Parameters["minRequiredNonalphanumericCharacters"] = txtMinRequiredNonAlphaChars.Text;
            pSettings.Parameters["passwordAttemptWindow"] = txtPasswordAttemptsWindow.Text;
            pSettings.Parameters["passwordStrengthRegularExpression"] = txtPasswordStrengthRegEx.Text;
        }

        protected void DeleteProvider(object sender, EventArgs e)
        {
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                System.Configuration.Configuration config = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~");
                System.Web.Configuration.MembershipSection mSection = (System.Web.Configuration.MembershipSection)config.GetSection("system.web/membership");
                mSection.Providers.Remove(txtProvidername.Text);
                config.Save(ConfigurationSaveMode.Minimal, false);
                Response.Redirect(Request.Url.AbsoluteUri.ToString() + "?Status=Success");
            });
        }
    }
}
